package com.zemb.flxwear.UI.Fragment;

import android.app.Fragment;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.res.Resources;
import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;

import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.zemb.flxwear.BLE.BLEUtils;
import com.zemb.flxwear.R;
import com.zemb.flxwear.UI.Activity.MeasureActivity;
import com.zemb.flxwear.Utils.DeviceUtils;
import com.zemb.flxwear.Utils.LogUtils;
import com.zemb.flxwear.Utils.VoicePlayUtils;

import java.util.List;


public abstract class BaseFragment extends Fragment {

    protected Bundle bundle;
    protected ConstraintLayout loadingPage;
    protected TextView alertText;

    protected String service_uuid = null;
    protected String characteristic_uuid = null;
    protected String device_uuid = null;
    protected Resources resources;
    public MeasureActivity activity;

    public boolean isAuto = false;
    public boolean isMeasure = false;

    public boolean isSuccessful = false;

    public boolean canPressBack = true;

    /***
     * 是否开启通知 这里的逻辑是当开启了通知后才算连接成功
     * 在连接上设备后就立马开启通知 如果没开启成功就尝试再次开启 最多尝试三次
     * 三次过后将不再尝试并且认为连接失败 如果是自动测量的话就结束当前测量并认为当前测量失败
     ***/
    public boolean isNotify = false;
    public int notifyCount = 0;

    //进度条
    abstract int getLoadingPageId();

    abstract int getLayoutId();

    //必须重写的方法 连接蓝牙通知


    abstract void onNotifyCallBack(byte[] data);

    //必须重写的方法 关闭蓝牙通知;
    abstract void closeNotify();

    //必须重写的方法 初始化view
    abstract void initView(View root);

    //必须重写的方法 初始化数据
    abstract void initData();

    //必须重写的方法 开始连接设备
    public abstract void onStartConnectDevice();

    //必须重写的方法 设备连接成功
    public abstract void onDeviceConnect(BleDevice bleDevice);

    //必须重写的方法 设备连接失败
    public abstract void onDeviceConnectFail(BleDevice bleDevice, BleException exception);

    //必须重写的方法 设备连接断开
    public abstract void onDeviceDisConnected(BleDevice bleDevice);

    //必须重写的方法 测量完成
    public abstract void onMeasureComplete();

    //必须重写的方法 测量开始
    public abstract void onMeasureStart();

    //只调用一次onMeasureStart
    public abstract String getCharacteristicHead();

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        //输出日志 类名+方法名
        LogUtils.PrintLog(this.getClass().getSimpleName() + " onCreate");
        super.onCreate(savedInstanceState);
        resources = getResources();
        activity = (MeasureActivity) getActivity();
        initData();

    }

    public void onMeasureFailed(){
        LogUtils.PrintLog(activity.getMeasureTag() + " onMeasureFailed");
        isMeasure=false;
        VoicePlayUtils.getInstance().PlayMeasureFailed(activity.getMeasureTag());
        hideLoading();
        if(isAuto){
            activity.passTask();
        }
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        //输出日志 类名+方法名
        LogUtils.PrintLog(this.getClass().getSimpleName() + " onCreateView");
        View root = inflater.inflate(getLayoutId(), container, false);
        loadingPage = root.findViewById(getLoadingPageId());
        alertText = root.findViewById(R.id.tv_alert);
        loadingPage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
        getBundleData();
        initView(root);
        //判断如果子类是ConnectFragment.class
        if (!(this instanceof ConnectFragment)) {
            //如果是ConnectFragment.class就不需要初始化UUID
            initUUId();
            initDevice();
        }
        return root;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        //输出日志 类名+方法名
        LogUtils.PrintLog(this.getClass().getSimpleName() + " onViewCreated");
    }

    protected String getResourceString(int id) {
        return resources.getString(id);
    }

    public long getCurrentTime() {
        return System.currentTimeMillis();
    }

    public void showLoading(String text) {
        loadingPage.setVisibility(View.VISIBLE);
        alertText.setText(text);
    }

    public void hideLoading() {
        loadingPage.setVisibility(View.GONE);
    }

    protected void getBundleData() {
        bundle = getBundle();
        if (bundle != null) {
            isAuto = bundle.getBoolean("isAuto");
        }
    }

    public void setBundleData(Bundle bundle) {
        this.bundle = bundle;
    }

    public Bundle getBundle() {
        if (bundle == null)
            bundle = new Bundle();
        return bundle;
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        //输出日志 类名+方法名
        LogUtils.PrintLog(this.getClass().getSimpleName() + " onHiddenChanged hidden:" + hidden);
        if (hidden) {
            //隐藏
            if (activity.getCurrentDevice() != null || service_uuid != null || characteristic_uuid != null || service_uuid != "None" || characteristic_uuid != "None") {
                closeNotify();

            }
            BleManager.getInstance().disconnectAllDevice();
        } else {
            //显示
            initUUId();
            initDevice();

        }
    }

    public void restart() {

    }

    public boolean notifyAdd() {
        notifyCount++;
        if (notifyCount > 3) {
            notifyCount = 0;
            return false;
        }
        return true;
    }


    //获取服务uuid和特征uuid 并且保存下来
    protected void initUUId() {
        device_uuid = DeviceUtils.getUUId(activity.getMeasureTag());
        service_uuid = DeviceUtils.getService(activity.getMeasureTag());
        characteristic_uuid = DeviceUtils.getCharacteristic(activity.getMeasureTag());

    }

    //当都存在UUId数据的时候考虑先连接蓝牙设备
    protected void initDevice() {
        if (device_uuid == null||device_uuid.isEmpty()) {
            return;
        }
        switch (getDeviceStatus()) {
            case DISCONNECTED:
                activity.ConnectDevice(device_uuid);
                break;
            case CONNECTED_TO_DIFFERENT_DEVICE:
                BleManager.getInstance().disconnect(activity.getCurrentDevice());
                activity.ConnectDevice(device_uuid);
                break;
            case CONNECTED_TO_MEASURE_TAG_DEVICE:
                notify();
                break;
            case NULL_DEVICE:
                activity.ConnectDevice(device_uuid);
                break;
        }
    }

    private int getDeviceStatus() {
        int status;
        if (activity.getCurrentDevice() == null||activity.getCurrentDevice().getName()==null||activity.getCurrentDevice().getName().isEmpty()) {
            status = NULL_DEVICE;
        } else if (!activity.getCurrentDevice().getName().equals(DeviceUtils.getDeviceName(activity.getMeasureTag()))) {
            status = CONNECTED_TO_DIFFERENT_DEVICE;
        } else if (activity.getCurrentDevice().getName().equals(DeviceUtils.getDeviceName(activity.getMeasureTag()))) {
            status = CONNECTED_TO_MEASURE_TAG_DEVICE;
        } else {
            status = DISCONNECTED;
        }
        return status;
    }

    private static final int NULL_DEVICE = 0;
    private static final int DISCONNECTED = 1;
    private static final int CONNECTED_TO_DIFFERENT_DEVICE = 2;
    private static final int CONNECTED_TO_MEASURE_TAG_DEVICE = 3;

    //在蓝牙设备连接成功之后 需要主动调用这个通知方法
    protected void openNotify() {
        if (service_uuid == null||service_uuid.isEmpty() || characteristic_uuid == null||characteristic_uuid.isEmpty()) {
            if (getServiceAndCharacteristic(getCharacteristicHead(), activity.getCurrentDevice())) {
                DeviceUtils.putService(activity.getMeasureTag(), service_uuid);
                DeviceUtils.putCharacteristic(activity.getMeasureTag(), characteristic_uuid);
            }
        }
        //输出
        if (service_uuid == null||service_uuid.isEmpty() || characteristic_uuid == null||characteristic_uuid.isEmpty()){
            activity.disconnectDevice(activity.getCurrentDevice());
            return;
        }
        LogUtils.PrintLog("openNotify", "service_uuid:" + service_uuid + " characteristic_uuid:" + characteristic_uuid);
        BleManager.getInstance().notify(activity.getCurrentDevice(), service_uuid, characteristic_uuid, new BleNotifyCallback() {
            @Override
            public void onNotifySuccess() {
                //打开通知成功
                LogUtils.PrintLog("onNotifySuccess", "打开通知成功");
                //当自动模式开启后 如果20秒后还没开始测量就失败
            }

            @Override
            public void onNotifyFailure(BleException exception) {
                //打开通知失败
                LogUtils.PrintLog("onNotifyFailure", exception.getDescription());
                if (notifyAdd()) {
                    openNotify();
                } else {

                    if (isAuto) {
                        activity.failTask();
                    }
                }
            }

            @Override
            public void onCharacteristicChanged(byte[] data) {
                //输出数据
                onNotifyCallBack(data);

            }
        });

    }

    //遍历所有的服务和特征并且找到对应的服务和特征
    public boolean getServiceAndCharacteristic(String characteristic_head, BleDevice device) {
        List<BluetoothGattService> services = BleManager.getInstance().getBluetoothGattServices(device);
        for (int i = 0; i < services.size(); i++) {

            List<BluetoothGattCharacteristic> gattCharacteristics = services.get(i).getCharacteristics();
            for (int j = 0; j < gattCharacteristics.size(); j++) {
//
                if (gattCharacteristics.get(j).getUuid().toString().contains(characteristic_head)) {
                    service_uuid = services.get(i).getUuid().toString();
                    characteristic_uuid = gattCharacteristics.get(j).getUuid().toString();
                    return true;

                }
            }
        }
        return false;
    }




}

